using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("umf.DLL", EntryPoint = "fw_init")]
        public static extern Int32 fw_init(Int16 port, Int32 baud);
        [DllImport("umf.DLL", EntryPoint = "fw_config_card")]
        public static extern Int32 fw_config_card(Int32 icdev, Byte flags);
        [DllImport("umf.DLL", EntryPoint = "fw_exit")]
        public static extern Int32 fw_exit(Int32 icdev);
        [DllImport("umf.Dll", EntryPoint = "fw_request")]
        public static extern Int32 fw_request(Int32 icdev, Byte _Mode,  UInt32[] TagType);
        [DllImport("umf.DLL", EntryPoint = "fw_anticoll")]
        public static extern Int32 fw_anticoll(Int32 icdev, Byte _Bcnt,  ulong[] _Snr);
        [DllImport("umf.DLL", EntryPoint = "fw_select")]
        public static extern Int32 fw_select(Int32 icdev, UInt32 _Snr,  Byte[] _Size);
        [DllImport("umf.DLL",EntryPoint="fw_card")]
        public static extern Int32 fw_card(Int32 icdev,Byte _Mode, ulong[] _Snr);
        [DllImport("umf.DLL",EntryPoint="fw_load_key")]
        public static extern Int32 fw_load_key(Int32 icdev,Byte _Mode,Byte _SecNr,Byte[] _NKey);
        [DllImport("umf.DLL",EntryPoint="fw_authentication")]
        public static extern Int32  fw_authentication(Int32 icdev,Byte _Mode,Byte _SecNr);
        [DllImport("umf.DLL",EntryPoint="fw_read")]
        public static extern  Int32  fw_read(Int32 icdev,Byte _Adr, Byte[] _Data);

        [DllImport("umf.dll",EntryPoint="fw_read_hex")]
        public static extern Int16 fw_read_hex(Int32 icdev, Byte _Adr, StringBuilder _Data);

        [DllImport("umf.DLL", EntryPoint = "fw_write")]
        public static extern  Int32  fw_write(Int32 icdev,Byte _Adr, Byte[] _Data);

        [DllImport("umf.dll", EntryPoint = "fw_write_hex")]
        public static extern Int16 fw_write_hex(Int32 icdev, Byte _Adr, string _Data);

        [DllImport("umf.DLL", EntryPoint = "fw_halt")]
        public static extern  Int32  fw_halt(Int32 icdev);
        [DllImport("umf.DLL", EntryPoint = "fw_changeb3")]
        public static extern Int32  fw_changeb3(Int32 icdev,Byte _SecNr, Byte[] _KeyA, Byte[] _CtrlW,Byte _Bk,
				 Byte[] _KeyB);
        [DllImport("umf.DLL", EntryPoint = "fw_initval")]
        public static extern Int32 fw_initval(Int32 icdev,Byte _Adr,UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_increment")]
        public static extern Int32 fw_increment(Int32 icdev,Byte _Adr,UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_readval")]
        public  static extern Int32 fw_readval(Int32 icdev,Byte _Adr, UInt32[] _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_decrement")]
        public static extern Int32  fw_decrement(Int32 icdev,Byte _Adr,UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_restore")]
        public static extern Int32  fw_restore(Int32  icdev,Byte _Adr);
        [DllImport("umf.DLL", EntryPoint = "fw_transfer")]
        public static extern Int32  fw_transfer(Int32 icdev,Byte _Adr);
        [DllImport("umf.DLL", EntryPoint = "fw_beep")]
        public static extern Int32  fw_beep(Int32 icdev,UInt32 _Msec);
        [DllImport("umf.DLL", EntryPoint = "fw_getver")]
        public static extern  Int32 fw_getver(Int32 icdev,byte[] buff);
        [DllImport("umf.DLL", EntryPoint = "fw_reset")]
        public static extern Int16  fw_reset(Int32 icdev,UInt16 _Msec);
        [DllImport("umf.DLL",EntryPoint="hex_a")]
        public static extern void hex_a(ref Byte hex,  Byte[] a,Int16 len);

        //Ultralight functions
        [DllImport("umf.dll",EntryPoint="fw_request_ultralt")]
        public static extern Int32 fw_request_ultralt(Int32 icdev, Byte _Mode);
        [DllImport("umf.dll",EntryPoint="fw_anticall_ultralt")]
        public static extern Int32 fw_anticall_ultralt(Int32 icdev,  ulong[] _Snr);
        [DllImport("umf.dll", EntryPoint = "fw_select_ultralt")]
        public static extern Int32 fw_select_ultralt(Int32 icdev, ulong _Snr);
        [DllImport("umf.dll", EntryPoint = "fw_write_ultralt")]
        public static extern Int32 fw_write_ultralt(Int32 icdev, Byte iPage,  Byte[] wdata);
        [DllImport("umf.dll", EntryPoint = "fw_read_ultralt")]
        public static extern Int32 fw_read_ultralt(Int32 icdev, Byte iPage,  Byte[] rdata);



        Int32 ihdev;
        Int32[] devs;//Array to save handle of devices
        Int32 state;
        bool isAuthen;
        bool isComOpen;
        Int32 curCardtype;

        Byte sector=6;//4;//M1 S70 test sector
        Byte Address = 24;//16;//The block to test, NOTE: don't set a key block
        //The last block of every sector if key block


        public Form1()
        {
            InitializeComponent();
            isComOpen = false;
            curCardtype = -1;
        }

        /// <summary>
        /// Open port
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
          

            Byte[] revbuf=new Byte[64];
            comboBox1.Items.Clear();

            if (!isComOpen)
            {
                /*Get the handle of reader*/
                Int32 tmphdev = 0;
                if (radioButton1.Checked == true)
                {//USB type
                    int i = 0;
                    do
                    {
                        tmphdev = fw_init(100, 0);
                        if (tmphdev != -1)
                        {
                            devs[i] = tmphdev;
                            string strdevs = "Device ";
                            strdevs += i.ToString();
                            comboBox1.Items.Add(strdevs);
                            i++;
                        }

                    }
                    while (i < 100 && tmphdev > 0);
		    
		    if(i >0)
		    {
                       ihdev = devs[0];
                       comboBox1.SelectedIndex = 0;
		    }
                }
                else
                {//Serial port
                    Int16 fport = Int16.Parse(comboBox2.SelectedIndex.ToString());

                    ihdev = fw_init(fport, 115200);//baud 115200

                    if (ihdev > 0)
                    {
                        comboBox1.Items.Add("Device 0");
                        comboBox1.SelectedIndex = 0;
                    }

                }

                if (ihdev > 0)
                {
                    listBox1.Items.Add("Open device ok！");
                    button1.Text = "Close device";
                    isComOpen = true;
                }
                else
                {
                    listBox1.Items.Add("Open device failed！");
                    return;
                }

                state = fw_getver(ihdev, revbuf);
                if (state != 0) listBox1.Items.Add("fw_getver Error");
                else
                {
                    listBox1.Items.Add("fw_getver OK");
                    ASCIIEncoding encod = new ASCIIEncoding();
                    listBox1.Items.Add(encod.GetString(revbuf));
                }
            }
            else
            {// Close reader
                int i = 0;
                while (devs[i] > 0)
                {
                    fw_exit(devs[0]);
                    devs[i] = 0;
                    i++;
                }

                if (ihdev > 0)
                    fw_exit(ihdev);

                ihdev = 0;

                comboBox1.Items.Clear();
                button1.Text = "Open device";

                isComOpen = false;
            }


        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ihdev = 0;
            devs = new Int32[100];
            for (int i = 0; i < 100; i++)
                devs[i] = 0;
            isAuthen=false;

            this.comboBox3.SelectedIndex = 0;
    

        }
        /// <Find Card>
        /// Find Card
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            ulong[] cardnumber = new ulong[3];//CardID
            //state = fw_config_card(ihdev, 0x41);   //Card Configure

            switch (curCardtype)
            {
                case 0:                              //Mifare 1K (S50)
                case 1:                              //S70
                    {
                        //fw_card
                        state = fw_card(ihdev, 1,  cardnumber);
                        if (state != 0) listBox1.Items.Add("fw_card Error");
                        else
                        {
                            listBox1.Items.Add("fw_card OK");
                        }

                        //fw_authentication
                        state = fw_authentication(ihdev, 0, sector );
                        if (state != 0) listBox1.Items.Add("fw_authentication Error");
                        else
                        {
                            listBox1.Items.Add("fw_authentication OK");
                            isAuthen = true;
                        }
                    }
                    break;
                case 2:
                    {
                        state = fw_request_ultralt(ihdev, 1);
                        state = fw_anticall_ultralt(ihdev,  cardnumber);
                        state = fw_select_ultralt(ihdev, cardnumber[0]);

                        if (state != 0)
                        {
                            listBox1.Items.Add("Find Card Error!");
                            return;
                        }
                        else
                        {
                            listBox1.Items.Add("Find Card Ok!");

                            listBox1.Items.Add(cardnumber[0]);
                        }
                    }
                    break;
                default:
                    break;
            }





        }
        /// <Load key>
        /// Load key
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            Byte[] key=new Byte[6];
            key[0]=0xff;
            key[1]=0xff;
            key[2]=0xff;
            key[3]=0xff;
            key[4]=0xff;
            key[5]=0xff;
            state = fw_load_key(ihdev, 0, sector, key);
            if (state != 0)
            {
                listBox1.Items.Add("fw_load_key Error");
                return;
            }
            listBox1.Items.Add("fw_load_key OK");


        }
        /// <Function test>
        /// Function test
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            switch (curCardtype)
            {
                case 0:                               //Mifare 1K(S50)
                case 1:                               //S70
                    {
                        if (!isAuthen)
                        {
                            MessageBox.Show("Call authen first!");
                            return;
                        }

                        isAuthen = false;

                        Byte[] sendbuf ={ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
                        Byte[] revbuf = new Byte[16];
                        Byte[] showbuf = new Byte[255];

                        string w_data = "11223344556677889900AABBCCDDEEFF";
                        StringBuilder r_data = new StringBuilder (300000);



                        //fw_write
                       // state = fw_write(ihdev, Address, ref sendbuf[0]);
                        state = fw_write_hex(ihdev, Address, w_data);
                        if (state != 0) listBox1.Items.Add("fw_write Error");
                        else listBox1.Items.Add("fw_write OK");

                        
                        //fw_read
                       // state = fw_read(ihdev, Address, ref revbuf[0]);
                        
                        state = fw_read_hex(ihdev, Address,  r_data);
                        if (state != 0) listBox1.Items.Add("fw_read Error");
                        else
                        {
                           // listBox1.Items.Add("fw_read OK");
                           // hex_a(ref showbuf[0], ref revbuf[0], 32);
                           // ASCIIEncoding encoding = new ASCIIEncoding();
                           // listBox1.Items.Add(encoding.GetString(showbuf));

                            listBox1.Items.Add(r_data.ToString());
                        }

                        //Chinese R/W test
                        //string strW = "IC卡读写器";
                        //Byte[] wBytes =new byte [20];
                        //if (strW.Length!=0)
                        //   wBytes = System.Text.Encoding.Default.GetBytes(strW);
                        //else
                        //    wBytes[0]=0;

                        //state = fw_write(ihdev, Address, ref wBytes[0]);
                        //if (state != 0) listBox1.Items.Add("fw_write Error");
                        //else listBox1.Items.Add("fw_write OK");
                        //读汉字
                        //state = fw_read(ihdev, Address, ref revbuf[0]);
                        //if (state != 0) listBox1.Items.Add("fw_read Error");
                        //else
                        //{
                        //    listBox1.Items.Add("fw_read OK");
                        //    ASCIIEncoding encoding = new ASCIIEncoding();
                        //    listBox1.Items.Add(Encoding.Default.GetString(revbuf));
                        //}

                        //fw_halt
                        state = fw_halt(ihdev);
                        if (state != 0) listBox1.Items.Add("fw_halt Error");
                        else listBox1.Items.Add("fw_halt OK");

                        isAuthen = false;
                    }
                    break;
                case 2:
                    {

                     
                        //Read block 0 before R/W
                        byte[] Data = new byte[6];
                        state = fw_read_ultralt(ihdev, 0,  Data);//Read page 0
                        if (state != 0)
                        {
                            listBox1.Items.Add("Read Page0 Error!");
                            return;
                        }


                        //Write card
                        char[] chars={'M', 'M', 'M', 'M' };
                        byte[] newCardData = Encoding.Default.GetBytes(chars);

                        state = fw_write_ultralt(ihdev, 4,  newCardData);

                        if (state != 0)
                        {
                            listBox1.Items.Add("fw_write_ultralt Error!");
                            return;
                        }

                        listBox1.Items.Add("fw_write_ultralt OK!");

                        //Read card
                        state = fw_read_ultralt(ihdev, 4,  Data);
                        if (state != 0)
                        {
                            listBox1.Items.Add("fw_read_ultralt Error!");
                            return;
                        }

                        listBox1.Items.Add("fw_read_ultralt Ok!");
                        listBox1.Items.Add(Encoding.Default .GetString (Data));
 
                    }
                    break;
                default:
                    break;
            }


        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button6_Click(object sender, EventArgs e)
        {
            //fw_reset
            state = fw_reset(ihdev, 10);
            if (state != 0) listBox1.Items.Add("fw_reset Error");
            else listBox1.Items.Add("fw_reset OK");

            //fw_beep
            state = fw_beep(ihdev, 10);
            if (state != 0)
            {
                listBox1.Items.Add("fw_beep Error");
                return;
            }
            listBox1.Items.Add("fw_beep OK");
            isAuthen = false;
        }
        /// <Update Key>
        /// 
        /// Update key
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, EventArgs e)
        {
            if (!isAuthen)
            {
                MessageBox.Show("Call authen first!");
                return;
            }

            isAuthen = false;
            Byte[] keya ={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
            Byte[] ctrlbyte ={ 0xff, 0x7, 0x80, 0x69 };
            Byte[] keyb ={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

            //fw_change3
            state = fw_changeb3(ihdev, sector,  keya,  ctrlbyte,0,  keyb);
            if (state != 0) listBox1.Items.Add("fw_changeb3 Error");
            else
            {
                listBox1.Items.Add("fw_changeb3 OK");
                isAuthen = false;
            }
        }
        /// < Value operation>
        /// Value operation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            //isAuthen = false;
            if (!isAuthen)
            {
                MessageBox.Show("Call authen first!");
                return;
            }

            isAuthen = false;
            uint[] value = new uint[3];

            //fw_initval
            state = fw_initval(ihdev, Address, 1000);
            if (state != 0) listBox1.Items.Add("fw_initval Error");
            else listBox1.Items.Add("fw_initval OK");

            //fw_readval
            state = fw_readval(ihdev, Address,  value);
            if (state != 0) listBox1.Items.Add("fw_readval Error");
            else
            {
                listBox1.Items.Add("fw_readval OK");
                listBox1.Items.Add(value[0]);
            }

            //fw_increment 
            state = fw_increment(ihdev, Address, 10);
            if (state != 0) listBox1.Items.Add("fw_increment Error");
            else
            {
                state = fw_transfer(ihdev, Address);
                if (state != 0) listBox1.Items.Add("fw_increment Error");
                else listBox1.Items.Add("fw_increment OK");
            }


            //fw_decrement
            state = fw_decrement(ihdev, Address, 5);
            if (state != 0) listBox1.Items.Add("fw_decrement Error");
            else
            {
                state = fw_transfer(ihdev, Address);
                if (state != 0) listBox1.Items.Add("fw_transfer Error");
                else
                {
                    listBox1.Items.Add("fw_transfer OK");
                    listBox1.Items.Add("fw_decrement OK");
                }
            }

            //fw_restore
            //state = fw_restore(ihdev, Address);  
            //if (state != 0) listBox1.Items.Add("fw_restore Error");
            //else listBox1.Items.Add("fw_restore OK");

        }

        private void radioButton1_Click(object sender, EventArgs e)
        {
            comboBox2.Visible = false;
        }

        private void radioButton2_Click(object sender, EventArgs e)
        {
            comboBox2.Visible = true;
            comboBox2.SelectedIndex = 0;
        }

        private void button9_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
        }

        /// <summary>
        /// Select card
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            curCardtype = comboBox3.SelectedIndex;

            if (2 == curCardtype)
            {
                setControlState(0);
            }
            else
                setControlState(1);
            
        }

        private void setControlState(int state)
        {
            if (state==1)
            {//case of S50/S70

                this.button7.Enabled = true;
                this.button8.Enabled = true;
            }
            else
            {

                this.button7.Enabled = false;
                this.button8.Enabled = false;
            }
        }
        /// <summary>
        /// Select reader
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox1_Click(object sender, EventArgs e)
        {
            ihdev = devs[comboBox1.SelectedIndex];
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

    }
}